﻿/** \file
* \$Rev: 183 $
* 
* \$Date: 2010-04-14 00:34:38 +0000 (Wed, 14 Apr 2010) $
*
* \$URL: http://chorus-twitter.googlecode.com/svn/trunk/src/gui/LinkedRTF.cs $
*/

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace chorus.gui
{
	/// <summary>
	/// The text box that contains Twitter text with links to users and web
	/// pages, etc.
	/// </summary>
	public partial class LinkedRTF : RichTextBox
	{
		/// <summary>The list of links in this text.</summary>
		List<Link> links = new List<Link>();
		/// <summary>The link currently under the cursor.</summary>
		Link currentLink = null;
		/// <summary>The Twitter message corresponding to this text.</summary>
		twitter.Message msg;
		/// <summary>Whether this text box is currently expanded to show more details.</summary>
		bool expanded;

		/// <summary>The message text.</summary>
		string Message { get { return msg.text; } }
		/// <summary>The message's status line.</summary>
		string Stat { get { return msg.StatLine; } }

		/// <summary>The constructor.</summary>
		/// <param name="msg">The Twitter message corresponding to this text.</param>
		public LinkedRTF(twitter.Message msg)
		{
			this.msg = msg;
			InitializeComponent();
			Contract();
			SetLinks();
		}

		/// <summary>Create links based on the message's text.</summary>
		void SetLinks()
		{
			SelectAll();
			SelectionColor = Color.Empty;

			if (expanded)
			{
				Select(Message.Length, Stat.Length + 2);
				Font font = new Font(SelectionFont.FontFamily, 7);
				SelectionFont = font;
			}

			links = LinkGenerator.GenerateAllLinks(Text);

			foreach (Link link in links)
			{
				Select(link.start, link.Length);
				SelectionColor = Color.Blue;
			}

			DeselectAll();
		}

		/// <summary>Contract the control to hide message details.</summary>
		public void Contract()
		{
			expanded = false;
			Text = Message;
		}

		/// <summary>Expand the control to show message details.</summary>
		public void Expand()
		{
			expanded = true;
			Text = Message
				+ Environment.NewLine + Environment.NewLine
				+ Stat;
		}

		#region Event handlers

		/// <summary>Fired when the text is clicked.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_MouseClick(object sender, MouseEventArgs e)
		{
			if (currentLink != null)
				currentLink.Click();
		}

		/// <summary>Fired when the mouse moves over this text.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_MouseMove(object sender, MouseEventArgs e)
		{
			int ichar = GetCharIndexFromPosition(new Point(e.X, e.Y));
			foreach (Link link in links)
			{
				if (link.Contains(ichar))
				{
					Point pchar = GetPositionFromCharIndex(ichar);
					if (e.Y < pchar.Y+Font.Height)
					{
						currentLink = link;
						if (link.NeedsFormatting)
							Cursor.Current = Cursors.Hand;
						return;
					}
				}
			}
			currentLink = null;
		}

		/// <summary>Fired when the control text changes.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_TextChanged(object sender, EventArgs e)
		{
			SetLinks();
		}

		/// <summary>Fired when the control is resized.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_ContentsResized(object sender, ContentsResizedEventArgs e)
		{
			Height = e.NewRectangle.Height + 5;
		}

		/// <summary>Fired when a link is clicked.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_LinkClicked(object sender, LinkClickedEventArgs e)
		{
			System.Diagnostics.Process.Start(e.LinkText);
		}

		/// <summary>Fired when the mouse enters the control region.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_MouseEnter(object sender, EventArgs e)
		{
			Expand();
		}

		/// <summary>Fired when the mouse leaves the control region.</summary>
		/// <param name="sender">The event sender.</param>
		/// <param name="e">The event parameters.</param>
		void LinkedRTF_MouseLeave(object sender, EventArgs e)
		{
			Contract();
		}

		#endregion
	}
}
